﻿using Heng.Elements.Core.Model.Infrastructure.Entities;
using Heng.Elements.Core.Model.Infrastructure.Repositories;
using Heng.Elements.Core.Model.Repository.EF.Infrastructure.Contexts;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Heng.Elements.Core.Model.Repository.EF.Infrastructure.Repositories
{
    /// <summary>
    /// Base Entity Framework Entity Repository implementation.
    /// </summary>
    /// <typeparam name="TEntity"> Entity type. </typeparam>
    /// <typeparam name="TContext"> Repository Context type. </typeparam>
    public abstract class EFEntityRepository<TEntity, TContext> : IEntityRepository<TEntity>
        where TEntity : class, IEntity
        where TContext : DbContext
    {
        #region Member Variables
        // repository context
        private DbContextFacade<TContext> _ctx = null;
        #endregion

        #region Properties
        /// <summary>
        /// Repository context.
        /// </summary>
        public IEntityRepositoryContext RepositoryContext
        {
            get { return _ctx; }
            set { _ctx = (DbContextFacade<TContext>)value; }
        }

        /// <summary>
        /// Repository context.
        /// </summary>
        protected DbContextFacade<TContext> ContextFacade
        {
            get { return _ctx; }
            private set { _ctx = value; }
        }
        #endregion

        /// <summary>
        /// Ctor.
        /// </summary>
        public EFEntityRepository()
        {
            // create repository context
            _ctx = new DbContextFacade<TContext>();
        }

        /// <summary>
        /// Get entity by ID.
        /// </summary>
        /// <param name="id"> Entity ID. </param>
        /// <returns> Entity. </returns>
        public virtual TEntity GetById(long id)
        {
            return this.ContextFacade.GetById<TEntity>(id);
        }

        /// <summary>
        /// Get all entities.
        /// </summary>
        /// <returns> Entities. </returns>
        public virtual IEnumerable<TEntity> GetAll()
        {
            return this.ContextFacade.GetAll<TEntity>();
        }

        /// <summary>
        /// Add entity.
        /// </summary>
        /// <param name="entity"> Entity instance to be added. </param>
        public virtual void Add(TEntity entity)
        {
            this.ContextFacade.Add(entity);
        }

        /// <summary>
        /// Save entity.
        /// </summary>
        /// <param name="entity"> Entity instance to be saved. </param>
        public virtual void Save(TEntity entity)
        {
            // nothing
        }

        /// <summary>
        /// Delete entity.
        /// </summary>
        /// <param name="entity"> Entity instance to delete. </param>
        public virtual void Delete(TEntity entity)
        {
            this.ContextFacade.Delete(entity);
        }

        /// <summary>
        /// Delete entity.
        /// </summary>
        /// <param name="id"> Entity ID to be deleted. </param>
        public virtual void Delete(long id)
        {
            this.ContextFacade.Delete<TEntity>(id);
        }

        /// <summary>
        /// Save all changes on current context.
        /// </summary>
        public virtual void SaveChanges()
        {
            this.ContextFacade.SaveChanges();
        }
    }
}
